package com.eight.cloud.admin.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.eight.cloud.admin.common.constant.CacheKeyConstant;
import com.eight.cloud.admin.entity.AppEntity;
import com.eight.cloud.admin.mapper.AppMapper;
import com.eight.cloud.admin.model.dto.AppDto;
import com.eight.cloud.admin.service.IAppService;
import com.eight.cloud.core.global.constant.UserTypeEnum;
import com.eight.cloud.core.global.exception.CustomException;
import com.eight.cloud.core.global.model.AppUser;
import com.eight.cloud.core.utils.format.RandomStrUtil;
import com.eight.cloud.core.utils.quick.DateUtil;
import com.eight.cloud.core.utils.quick.RSAUtils;
import com.eight.cloud.mybatisplus.entity.BaseEntity;
import com.eight.cloud.mybatisplus.service.BaseService;
import com.eight.cloud.openfeign.admin.vo.AppVo;
import com.eight.cloud.redisson.model.TypedKey;
import com.eight.cloud.redisson.utils.RedisUtils;
import com.fasterxml.jackson.core.type.TypeReference;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.util.List;

import static com.eight.cloud.core.global.constant.NumConstant.*;

/**
 * app信息表 服务实现类
 *
 * @ClassName: AppServiceImpl
 * @Author TXC
 * @Date 2025-01-07 17:34
 */
@Service
public class AppServiceImpl extends BaseService<AppMapper, AppEntity> implements IAppService {
    @Resource
    private RedisUtils redisUtils;

    @Override
    public AppVo create(AppDto app) {
        AppEntity appEntity = convertToEntity(app);
        List<String> keyPair = RSAUtils.generateKeyPair(1024);
        String secretKey = RandomStrUtil.getRandomStr(LONG_SIZE);
        String secretId = RandomStrUtil.getRandomStr(INT_SIZE);
        String encryptSecretKey = RSAUtils.encrypt(secretKey);
        appEntity.setPublicKey(keyPair.get(ZERO));
        appEntity.setPrivateKey(keyPair.get(ONE));
        appEntity.setSecretId(secretId);
        appEntity.setSecretKey(encryptSecretKey);
        appEntity.setUuid(generateAppId());
        baseMapper.insert(appEntity);
        return convertToObject(appEntity, AppVo.class);
    }

    @Override
    public boolean edit(AppDto appDto) {
        if (ObjectUtil.isEmpty(appDto.getUuid())) {
            throw new CustomException(500, "app未找到");
        }
        AppEntity app = baseMapper.selectOne(lambdaQueryWrapper().eq(BaseEntity::getUuid, appDto.getUuid()));
        app.setName(appDto.getName());
        app.setDescription(appDto.getDescription());
        baseMapper.updateById(app);
        redisUtils.delete(CacheKeyConstant.generateKey(CacheKeyConstant.ADMIN_APP_UUID, appDto.getUuid()));
        return baseMapper.updateById(app) > 0;
    }

    @Override
    public AppVo detail(String uuid) {
        String cacheKey = CacheKeyConstant.generateKey(CacheKeyConstant.ADMIN_APP_UUID, uuid);
        return redisUtils.cacheOrFetch(
                TypedKey.<AppVo>builder().key(cacheKey).type(new TypeReference<>() {}).build(),
                () -> {
                    AppEntity app = getByUuid(uuid);
                    if (ObjectUtil.isNull(app)) {
                        return null;
                    }
                    return convertToObject(app, AppVo.class);
                }, WEEK_SECONDS);
    }

    @Override
    public AppUser getAppBySecretId(String secretId) {
        String cacheKey = CacheKeyConstant.generateKey(CacheKeyConstant.ADMIN_APP_SECRET, secretId);
        String appid = redisUtils.cacheOrFetch(
                TypedKey.<String>builder().key(cacheKey).type(new TypeReference<>() {}).build(),
                () -> {
                    AppEntity app = baseMapper.selectOne(lambdaQueryWrapper().eq(AppEntity::getSecretId, secretId));
                    if (ObjectUtil.isNull(app)) {
                        return null;
                    }
                    return app.getUuid();
                }, WEEK_SECONDS);
        return getAppByUuid(appid);
    }

    @Override
    public AppUser getAppByUuid(String appid) {
        AppVo appVo = detail(appid);
        AppUser appUser = BeanUtil.copyProperties(appVo, AppUser.class);
        appUser.setUserType(UserTypeEnum.APP);
        return appUser;
    }


    @Override
    public String updateSecretKey(String uuid) {
        String secretKey = RandomStrUtil.getRandomStr(LONG_SIZE);
        String encryptSecretKey = RSAUtils.encrypt(secretKey);
        baseMapper.update(lambdaUpdateWrapper().set(AppEntity::getSecretKey, encryptSecretKey)
                .eq(BaseEntity::getUuid, uuid));
        redisUtils.delete(CacheKeyConstant.generateKey(CacheKeyConstant.ADMIN_APP_UUID, uuid));
        return encryptSecretKey;
    }

    @Override
    public String generateAppId() {
        LocalDate today = LocalDate.now();
        String year = String.valueOf(today.getYear());
        String dayOfYear = String.format("%03d", today.getDayOfYear());
        // 获取当天结束时间戳
        Long expireTimestamp = DateUtil.endOfDayTimestamp();
        return year + dayOfYear + String.format("%03d", redisUtils.getLongIncr(CacheKeyConstant.ADMIN_APP_ID_INCR, expireTimestamp));
    }
}
